//package com.yc.psychologicalconsultant.interceptor;
//
//import com.alibaba.fastjson.JSONObject;
//import com.yc.psychologicalconsultant.pojo.Result;
//import com.yc.psychologicalconsultant.utils.JwtUtils;
//import jakarta.servlet.http.HttpServletRequest;
//import jakarta.servlet.http.HttpServletResponse;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.stereotype.Component;
//import org.springframework.util.StringUtils;
//import org.springframework.web.servlet.HandlerInterceptor;
//import org.springframework.web.servlet.ModelAndView;
//
//@Slf4j
//@Component
//public class LoginInterceptor implements HandlerInterceptor {
//    @Override
//    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//
//        //1.背景
//        //起初解决Springboot跨域问题的方法是直接在Controller上添加@CrossOrigin注解，实现了前后端分离中的跨域请求。但随着业务代码的编写，做了token会话保持的检验，添加了拦截器后，再次出现了跨域问题。很纳闷，讲理说后台已经允许了跨域请求，之前的测试也证明了这一点，那为什么又突然出现了跨域拦截问题呢？
//        //
//        //
//        //2.分析及解决方案
//        //在登录拦截器中作了校验，对于需要登录后才能访问的接口，如果请求头中没有携带token，则是非法请求，直接返回404码。然后由于一直有对拦截到的请求中的请求头中的token做打印，所以出现问题的时候，控制台打印的token值为null，打开浏览器的开发者工具查看请求头也发现没有携带成功。而在没有添加拦截器之前上述问题都是不存在的，都是正常的，所以都不用考虑是前端问题，问题肯定出在后端，准确的说是拦截器。
//        //
//        //那么为什么浏览器不能成功发送token呢？根据线索在更详细的查看了CROS的介绍后发现，原来CROS复杂请求时会首先发送一个OPTIONS请求做嗅探，来测试服务器是否支持本次请求，请求成功后才会发送真实的请求；而OPTIONS请求不会携带任何数据，导致这个请求不符合我们拦截器的校验规则被拦截了，直接返回了状态码，响应头中也没携带解决跨域需要的头部信息，进而出现了跨域问题。所以在浏览器调试工具中会发现该次请求没有携带token，后端控制台打印token也为null。
//        //
//        //但是，就算这样，为什么会发生在添加跨域相关头部信息前就提前结束请求的这种情况呢？难道自定义的拦截器优先于@CrossOrigin注解执行？
//        //
//        //通过查阅资料，解析@CrossOrigin注解的源码得知，如果Controller在类上标了@CrossOrigin或在方法上标了@CrossOrigin注解，则Spring 在记录mapper映射时会记录对应跨域请求映射，将结果返回到AbstractHandlerMethodMapping，当一个跨域请求过来时，Spring在获取handler时会判断这个请求是否是一个跨域请求，如果是，则会返回一个可以处理跨域的handler。总结起来@CrossOrigin的原理相当于和Handler进行强绑定。
//        //
//        //于是现在的问题又到了：Handler和拦截器的执行顺序？
//        //
//        //DispatchServlet.doDispatch()方法是SpringMVC的核心入口方法，经过分析发现所有的拦截器的preHandle()方法的执行都在实际handler的方法（比如某个API对应的业务方法）之前，其中任意拦截器返回false都会跳过后续所有处理过程。而SpringMVC对预检请求的处理则在PreFlightHandler.handleRequest()中处理，在整个处理链条中出于后置位。由于预检请求中不带数据，因此先被权限拦截器拦截了。
//        //
//        //所以每次获取不到token的请求都是OPTIONS请求，那么解决的方法就很明了了：把所有的OPTIONS请求统统放行。
//        //
//        ////拦截器取到请求先进行判断，如果是OPTIONS请求，则放行
//        //if("OPTIONS".equals(httpServletRequest.getMethod().toUpperCase())) {
//        //    System.out.println("Method:OPTIONS");
//        //	return true;
//        // }
//        //1
//        //2
//        //3
//        //4
//        //5
//        //测试一下，发现打印有OPTIONS的提示，说明确实存在OPTIONS请求，并且成功解决了问题。
//        //————————————————
//        if ("OPTIONS".equals(request.getMethod().toUpperCase())) {
//            System.out.println("Method:OPTIONS");
//            return true;
//        }
//        System.out.println("preHandle......");
//        String url = request.getRequestURL().toString();
//        log.info("请求的url：{}", url);
//        if (url.contains("login")) {
//            log.info("登录操作");
//            return true;
//        }
//        if (url.contains("register")) {
//            log.info("注册操作");
//            return true;
//        }
//
//        String jwt = request.getHeader("token");
//        if (!StringUtils.hasLength(jwt)) {
//            log.info("请求头token为空，返回未登录信息");
//            Result error = Result.error("NOT_LOGIN");
//            String NotLogin = JSONObject.toJSONString(error);
//            response.getWriter().write(NotLogin);
//            return false;
//        }
//        try {
//            JwtUtils.parseJWT(jwt);
//        } catch (Exception e) {
//            e.printStackTrace();
//            log.info("解析令牌失败，返回未登录的错误信息");
//            Result error = Result.error("NOT_LOGIN");
//            String s = JSONObject.toJSONString(error);
//            response.getWriter().write(s);
//            return false;
//        }
//        log.info("合法令牌放行");
//        return true;
//    }
//
//    @Override
//    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//
//        System.out.println("postHandle......");
//
//    }
//
//    @Override
//    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//        System.out.println("afterCompletion");
//    }
//}
